home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 26 / Cream of the Crop 26.iso / os2 / plnk081.zip / pilot-link.0.8.1 / pilot-mail.c.orig < prev    next >
Text File  |  1997-08-06  |  21KB  |  906 lines

  1. /* pilot-mail.c:  Make mail go voom-voom tween da Pilot an da Net
  2.  *
  3.  * Copyright (c) 1997, Kenneth Albanowski
  4.  *
  5.  * This is free software, licensed under the GNU Public License V2.
  6.  * See the file COPYING for details.
  7.  *
  8.  * Modifications by Diego Zamboni to allow it to read mail from an MH-style
  9.  * mailbox into the Pilot.
  10.  *
  11.  */
  12.  
  13. #define PILOTPORT    ""
  14. #define POPHOST     ""
  15. #define POPUSER        ""
  16. #define POPPASS        ""
  17. #define PILOTFROM    ""
  18. #define SENDMAIL    "/usr/lib/sendmail -t -i"
  19. #define POPKEEP     "keep"
  20. #define DISPOSE        "keep"
  21. #define TOPILOT_MHDIR   ""
  22.  
  23. /* Todo: truncation, filtering, priority, notification */
  24.  
  25. #include <stdio.h>
  26. #include <stdlib.h>
  27. #include <string.h>
  28. #include <unistd.h>
  29. #include "pi-source.h"
  30. #include "pi-socket.h"
  31. #include "pi-mail.h"
  32. #include "pi-dlp.h"
  33. #include <signal.h>
  34.  
  35. #include <sys/types.h>
  36. #include <sys/socket.h>
  37. #include <netinet/in.h>
  38. #include <arpa/inet.h>
  39. #include <netdb.h>
  40.  
  41. extern time_t parsedate(char * p);
  42.  
  43. void markline(char *msg) {
  44.     while((*msg)!='\n' && (*msg)!=0 ) {
  45.     msg++;
  46.     }
  47.     (*msg)=0;
  48. }
  49.  
  50. int openmhmsg(char *dir, int num) {
  51.     char filename[1000];
  52.  
  53.  
  54.     sprintf(filename, "%s/%d", dir, num);
  55.  
  56.     return open(filename, O_RDONLY);
  57. }
  58.  
  59. /* Fold into RFC822 style*/
  60. void fprintfold(FILE * f, char * t)
  61. {
  62.   while(*t) {
  63.     if ((*t == '\r') || (*t == '\n')) {
  64.       fprintf(f, "\r\n ");
  65.     }
  66.     else {
  67.       putc(*t, f);
  68.     }
  69.     t++;
  70.   }
  71. }
  72.  
  73. /* Translate into sendmail body style */
  74. void fprintbody(FILE * f, char * t)
  75. {
  76.   int c = 1;
  77.   while(*t) {
  78.     if ((*t == '\r') || (*t == '\n')) {
  79.       fprintf(f,"\r\n");
  80.       c = 0;
  81.     }
  82.     else {
  83.       if ((c == 0) && (*t == '.'))
  84.         putc('.', f);
  85.       putc(*t, f);
  86.       c++;
  87.     }
  88.     t++;
  89.   }
  90. }
  91.  
  92. int getpopchar(int socket)
  93. {
  94.   unsigned char buf;
  95.   int l;
  96.   
  97.   do {
  98.     l = read(socket, &buf, 1);
  99.     if (l < 0)
  100.       return l;
  101.   } while ((l==0) || (buf == '\r'));
  102.   
  103.   return buf;
  104. }
  105.  
  106. int getpopstring(int socket, char * buf)
  107. {
  108.   int c;
  109.   while ((c = getpopchar(socket)) >= 0) {
  110.     *buf++ = c;
  111.     if (c == '\n')
  112.       break;
  113.   }
  114.   *buf = '\0';
  115.   return c;
  116. }
  117.  
  118. int getpopresult(int socket, char * buf)
  119. {
  120.   int c = getpopstring(socket, buf);
  121.   
  122.   if (c<0)
  123.     return c;
  124.   
  125.   if (buf[0] == '+')
  126.     return 0;
  127.   else
  128.     return 1;
  129. }
  130.  
  131. char * skipspace(char * c) {
  132.   while (c && ((*c == ' ') || (*c == '\t')))
  133.     c++;
  134.   return c;
  135. }
  136.  
  137. void header(struct Mail * m, char * t)
  138. {
  139.   static char holding[4096];
  140.   
  141.   if (t && strlen(t) && t[strlen(t)-1] == '\n')
  142.     t[strlen(t)-1] = 0;
  143.   
  144.   if (t && ((t[0] == ' ') || (t[0] == '\t'))) {
  145.     if ((strlen(t) + strlen(holding)) > 4096)
  146.       return; /* Just discard approximate overflow */
  147.     strcat(holding, t+1);
  148.     return;
  149.   }
  150.   
  151.   /* Decide on what we do with m->sendTo */
  152.   
  153.   if (strncmp(holding, "From:", 5)==0) {
  154.     m->from = strdup(skipspace(holding+5));
  155.   } else if (strncmp(holding, "To:",3)==0) {
  156.     m->to = strdup(skipspace(holding+3));
  157.   } else if (strncmp(holding, "Subject:",8)==0) {
  158.     m->subject = strdup(skipspace(holding+8));
  159.   } else if (strncmp(holding, "Cc:",3)==0) {
  160.     m->cc = strdup(skipspace(holding+3));
  161.   } else if (strncmp(holding, "Bcc:",4)==0) {
  162.     m->bcc = strdup(skipspace(holding+4));
  163.   } else if (strncmp(holding, "Reply-To:",9)==0) {
  164.     m->replyTo = strdup(skipspace(holding+9));
  165.   } else if (strncmp(holding, "Date:",4)==0) {
  166.     time_t d = parsedate(skipspace(holding+5));
  167.     if (d != -1) {
  168.       struct tm * d2;
  169.       m->dated = 1;
  170.       d2 = localtime(&d);
  171.       m->date = *d2;
  172.     }
  173.   }
  174.   
  175.   holding[0] = 0;
  176.   
  177.   if (t)
  178.     strcpy(holding, t);
  179. }
  180.  
  181.  
  182. void Help(char * progname)
  183. {
  184.   fprintf(stderr,"usage: %s [options]\n",progname);
  185.   fprintf(stderr,"\n      <-p port> Serial port [PILOTPORT]");
  186.   fprintf(stderr,"\n                   (defaults to '%s')", PILOTPORT);
  187.   fprintf(stderr,"\n      <-h host> POP3 host (if empty, mail won't be received) [POPHOST]");
  188.   fprintf(stderr,"\n                   (defaults to '%s')", POPHOST);
  189.   fprintf(stderr,"\n      <-u user> POP3 user name [POPUSER]");
  190.   fprintf(stderr,"\n                   (defaults to '%s')", POPUSER);
  191.   fprintf(stderr,"\n      <-P pass> POP3 password [POPPASS]");
  192.   fprintf(stderr,"\n                   (default value set)");
  193.   fprintf(stderr,"\n      <-f address> Outgoing 'From:' line [PILOTFROM]");
  194.   fprintf(stderr,"\n                   (defaults to '%s')", PILOTFROM);
  195.   fprintf(stderr,"\n      <-s command> Sendmail command (if empty, mail won't be sent) [SENDMAIL]");
  196.   fprintf(stderr,"\n                   (defaults to '%s')", SENDMAIL);
  197.   fprintf(stderr,"\n      <-k keep|delete> Keep mail on POP server [POPKEEP]");
  198.   fprintf(stderr,"\n                   (defaults to '%s')", POPKEEP);
  199.   fprintf(stderr,"\n      <-d keep|delete|file> Disposition of sent mail [PILOTDISPOSE]");
  200.   fprintf(stderr,"\n                   (defaults to '%s')", DISPOSE);
  201.   fprintf(stderr,"\n      <-m mhdir> MH directory to download to Pilot [TOPILOT_MHDIR]");
  202.   fprintf(stderr,"\n                   (defaults to '%s')", TOPILOT_MHDIR);
  203.   fprintf(stderr, "\n\nAll options may be specified via the environment variable named in brackets.\n");
  204.   exit(0);
  205. }
  206.  
  207. void sigint(int num)
  208. {
  209.   *((char*)0)=0;
  210. }
  211.                   
  212. int main(int argc, char *argv[])
  213. {
  214.   struct pi_sockaddr addr;
  215.   int db;
  216.   int sd;
  217.   int i,l;
  218.   int lost,dupe,rec,sent;
  219.   struct PilotUser U;
  220.   int ret;
  221.   unsigned char buffer[0xffff];
  222.   struct MailAppInfo tai;
  223.   struct MailSyncPref p;
  224.   struct MailSignaturePref sig;
  225.   struct sockaddr_in pop_addr;
  226.   int popfd;
  227.   struct hostent * hostent;
  228.   int c;
  229.   char * progname = argv[0];
  230.   
  231.   char * from_address = 
  232. #ifdef PILOTFROM
  233.   PILOTFROM;
  234. #else
  235.   "";
  236. #endif
  237.   char * pop_host = 
  238. #ifdef POPHOST
  239.   POPHOST;
  240. #else
  241.   "";
  242. #endif
  243.   char * pop_user =
  244. #ifdef POPUSER
  245.   POPUSER;
  246. #else
  247.   "";
  248. #endif
  249.   char * pop_pass =
  250. #ifdef POPPASS
  251.   POPPASS;
  252. #else
  253.   "";
  254. #endif
  255.   char * sendmail =
  256. #ifdef SENDMAIL
  257.   SENDMAIL;
  258. #else
  259.   "";
  260. #endif
  261.   char * pop_keep =
  262. #ifdef POPKEEP
  263.   POPKEEP;
  264. #else
  265.   "";
  266. #endif
  267.   char * dispose =
  268. #ifdef DISPOSE
  269.   DISPOSE;
  270. #else
  271.   "";
  272. #endif
  273.   char * port =
  274. #ifdef PILOTPORT
  275.   PILOTPORT;
  276. #else
  277.   "";
  278. #endif
  279.   char * mh_dir =
  280. #ifdef TOPILOT_MHDIR
  281.   TOPILOT_MHDIR;
  282. #else
  283.   "";
  284. #endif
  285.  
  286.   extern char* optarg;
  287.   extern int optind;
  288.   
  289.  
  290.   if (getenv("SENDMAIL"))
  291.     sendmail = getenv("SENDMAIL");
  292.   if (getenv("POPKEEP"))
  293.     pop_keep = getenv("POPKEEP");
  294.   if (getenv("PILOTDISPOSE"))
  295.     dispose = getenv("PILOTDISPOSE");
  296.   if (getenv("PILOTFROM"))
  297.     from_address = getenv("PILOTFROM");
  298.   if (getenv("POPHOST"))
  299.     pop_host = getenv("POPHOST");
  300.   if (getenv("POPUSER"))
  301.     pop_user = getenv("POPUSER");
  302.   if (getenv("POPPASS"))
  303.     pop_pass = getenv("POPPASS");
  304.   if (getenv("PILOTPORT"))
  305.     port = getenv("PILOTPORT");
  306.   if (getenv("TOPILOT_MHDIR"))
  307.     mh_dir = getenv("TOPILOT_MHDIR");
  308.      
  309.   signal(SIGINT, sigint);
  310.  
  311.   while ((c = getopt(argc, argv, "s:p:d:f:h:u:p:h:P:k:m:")) != EOF) {
  312.     switch (c) {
  313.       case 's':
  314.         sendmail = optarg;
  315.         break;
  316.       case 'p':
  317.         port = optarg;
  318.         break;
  319.       case 'h':
  320.         pop_host = optarg;
  321.         break;
  322.       case 'u':
  323.         pop_user = optarg;
  324.         break;
  325.       case 'P':
  326.         pop_pass = optarg;
  327.         break;
  328.       case 'f':
  329.         from_address = optarg;
  330.         break;
  331.       case 'd':
  332.         dispose = optarg;
  333.         break;
  334.       case 'k':
  335.         pop_keep = optarg;
  336.         break;
  337.       case 'm':
  338.     mh_dir = optarg;
  339.     break;
  340.       case 'H': case '?': default:
  341.         Help(progname);
  342.     }
  343.   }
  344.   argc -= optind;
  345.   argv += optind;
  346.   
  347.   if (!strlen(port)) {
  348.     fprintf(stderr, "Port must be set.\n\n");
  349.     Help(progname);
  350.   }
  351.   
  352.   
  353.   if (!strlen(pop_host) && !strlen(sendmail)) {
  354.     fprintf(stderr, "At least one of -h or -s must be set.\n\n");
  355.     Help(progname);
  356.   }
  357.   
  358.   if (strlen(pop_host)) {
  359.     if (!strlen(pop_user)) {
  360.       fprintf(stderr, "-u must be set to receive mail.\n\n");
  361.       Help(progname);
  362.     } else if (!strlen(pop_keep) || (strcmp(pop_keep, "keep") && strcmp(pop_keep,"delete"))) {
  363.       fprintf(stderr, "-k must have an argument of 'keep' or 'delete'.\n\n");
  364.       Help(progname);
  365.     } 
  366.   }
  367.  
  368.   if ( !strlen( pop_pass ) && strlen( pop_host ) )
  369.     {
  370.       pop_pass = getpass( "POP password: " );
  371.     }
  372.   
  373.   if (strlen(sendmail)) {
  374.     if (!strlen(dispose) || (strcmp(dispose,"keep") &&
  375.                              strcmp(dispose,"delete") &&
  376.                              strcmp(dispose,"file"))) {
  377.       fprintf(stderr, "-d must have an argument of 'keep', 'delete', or 'file'.\n\n");
  378.       Help(progname);
  379.     }
  380.   }
  381.   
  382.   if (!(sd = pi_socket(PI_AF_SLP, PI_SOCK_STREAM, PI_PF_PADP))) {
  383.     perror("pi_socket");
  384.     exit(1);
  385.   }
  386.   
  387.   lost = dupe = rec = sent = 0;
  388.   
  389.   addr.pi_family = PI_AF_SLP;
  390.   strcpy(addr.pi_device, port);
  391.   
  392.   ret = pi_bind(sd, (struct sockaddr*)&addr, sizeof(addr));
  393.   if(ret == -1) {
  394.     perror("pi_bind");
  395.     exit(1);
  396.   }
  397.  
  398.   ret = pi_listen(sd,1);
  399.   if(ret == -1) {
  400.     perror("pi_listen");
  401.     exit(1);
  402.   }
  403.  
  404.   sd = pi_accept(sd, 0, 0);
  405.   if(sd == -1) {
  406.     perror("pi_accept");
  407.     exit(1);
  408.   }
  409.   
  410.   memset(&tai, '\0', sizeof(struct MailAppInfo));
  411.   memset(&p, '\0', sizeof(struct MailSyncPref));
  412.  
  413.   /* Ask the pilot who it is. */
  414.   dlp_ReadUserInfo(sd,&U);
  415.   
  416.   /* Tell user (via Pilot) that we are starting things up */
  417.   dlp_OpenConduit(sd);
  418.   
  419.   /* Open the Mail database, store access handle in db */
  420.   if(dlp_OpenDB(sd, 0, 0x80|0x40, "MailDB", &db) < 0) {
  421.     fprintf(stderr, "Unable to open MailDB\n");
  422.     dlp_AddSyncLogEntry(sd, "Unable to open MailDB.\n");
  423.     exit(1);
  424.   }
  425.   
  426.   dlp_ReadAppBlock(sd, db, 0, buffer, 0xffff);
  427.   unpack_MailAppInfo(&tai, buffer, 0xffff);
  428.   
  429.   setbuf(stderr, 0);
  430.   
  431.   p.syncType = 0;
  432.   p.getHigh = 0;
  433.   p.getContaining = 0;
  434.   p.truncate = 8*1024;
  435.   p.filterTo = 0;
  436.   p.filterFrom = 0;
  437.   p.filterSubject = 0;
  438.   
  439.   if (pi_version(sd) > 0x0100) {
  440.     if (dlp_ReadAppPreference(sd, makelong("mail"), 1, 1, 0xffff, buffer, 0, 0)>=0) {
  441.       printf("Got local backup mail preferences\n"); /* 2 for remote prefs */
  442.       unpack_MailSyncPref(&p, buffer, 0xffff);
  443.     } else {
  444.       printf("Unable to get mail preferences, trying current\n");
  445.       if (dlp_ReadAppPreference(sd, makelong("mail"), 1, 1, 0xffff, buffer, 0, 0)>=0) {
  446.         printf("Got local current mail preferences\n"); /* 2 for remote prefs */
  447.         unpack_MailSyncPref(&p, buffer, 0xffff);
  448.       } else
  449.         printf("Couldn't get any mail preferences.\n");
  450.     }
  451.     
  452.     if (dlp_ReadAppPreference(sd, makelong("mail"), 3, 1, 0xffff, buffer, 0, 0)>0) {
  453.       unpack_MailSignaturePref(&sig, buffer, 0xffff);
  454.     }
  455.  
  456.   }
  457.  
  458.   printf("Local Prefs: Sync=%d, High=%d, getc=%d, trunc=%d, to=|%s|, from=|%s|, subj=|%s|\n",
  459.      p.syncType, p.getHigh, p.getContaining, p.truncate, p.filterTo ? p.filterTo : "<none>",
  460.      p.filterFrom ? p.filterFrom : "<none>", p.filterSubject ? p.filterSubject : "<none>");
  461.  
  462.   printf("AppInfo Signature: |%s|\n\n", sig.signature ? sig.signature : "<None>");
  463.  
  464. #if 0
  465.   for (i=0;1;i++) {
  466.       struct Mail t;
  467.       int attr, category;
  468.                                  
  469.       int len = dlp_ReadRecordByIndex(sd, db, i, buffer, 0, 0, &attr, &category);
  470.       if(len<0)
  471.           break;
  472.           
  473.       /* Skip deleted records */
  474.       if((attr & dlpRecAttrDeleted) || (attr & dlpRecAttrArchived))
  475.           continue;
  476.           
  477.     unpack_Mail(&t, buffer, len);
  478.     
  479.     printf("Category: %s\n", tai.CategoryName[category]);
  480.     printf("Read: %d, Signature: %d, confirmRead: %d, confirmDeliver: %d, priority: %d, address: %d\n",
  481.            t.read, t.signature, t.confirmRead, t.confirmDelivery, t.priority, t.addressing);
  482.         printf("Time: %s", t.dated ? asctime(&t.date) : "<Undated>");
  483.         printf("Subject: |%s|\n", t.subject ? t.subject : "<None>");
  484.         printf("From: |%s|\n", t.from ? t.from : "<None>");
  485.         printf("To: |%s|\n", t.to ? t.to : "<None>");
  486.         printf("Cc: |%s|\n", t.cc ? t.cc : "<None>");
  487.         printf("Bcc: |%s|\n", t.bcc ? t.bcc : "<None>");
  488.         printf("ReplyTo: |%s|\n", t.replyTo ? t.replyTo : "<None>");
  489.         printf("SendTo: |%s|\n", t.sentTo ? t.sentTo : "<None>");
  490.         printf("Body: |%s|\n", t.body ? t.body : "<None>");
  491.     printf("\n");
  492.  
  493.     free_Mail(&t);
  494.   }
  495. #endif
  496.  
  497.   if (strlen(sendmail)) {
  498.   /* sendmail transmission section */
  499.  
  500.   /* Iterate over messages in Outbox */
  501.   for (i=0;1;i++) {
  502.       struct Mail t;
  503.       int attr;
  504.       int size;
  505.       recordid_t id;
  506.       FILE * sendf;
  507.                                  
  508.       int len = dlp_ReadNextRecInCategory(sd, db, 1, buffer, &id, 0, &size, &attr);
  509.       if(len<0)
  510.           break;
  511.           
  512.       /* Skip deleted records */
  513.       if((attr & dlpRecAttrDeleted) || (attr & dlpRecAttrArchived))
  514.           continue;
  515.           
  516.     unpack_Mail(&t, buffer, len);
  517.  
  518.       sendf = popen(sendmail, "w");
  519.       
  520.       if (!sendf) {
  521.         fprintf(stderr,"Error launching '%s' to transmit mail! (No mail lost, %d received, %d sent)\n",
  522.                 sendmail, rec, sent);
  523.         pi_close(sd);
  524.         exit(1);
  525.       }
  526.     
  527.     if (from_address) {
  528.       fprintf(sendf,"From: ");
  529.       fprintf(sendf, from_address);
  530.       fprintf(sendf,"\r\n");
  531.     }
  532.  
  533.     if (t.to) {
  534.       fprintf(sendf,"To: ");
  535.       fprintfold(sendf,t.to);
  536.       fprintf(sendf,"\r\n");
  537.     }
  538.     if (t.cc) {
  539.       fprintf(sendf,"Cc: ");
  540.       fprintfold(sendf,t.cc);
  541.       fprintf(sendf,"\r\n");
  542.     }
  543.     if (t.bcc) {
  544.       fprintf(sendf,"Bcc: ");
  545.       fprintfold(sendf,t.bcc);
  546.       fprintf(sendf,"\r\n");
  547.     }
  548.     if (t.replyTo) {
  549.       fprintf(sendf,"Reply-To: ");
  550.       fprintfold(sendf,t.replyTo);
  551.       fprintf(sendf,"\r\n");
  552.     }
  553.     if (t.subject) {
  554.       fprintf(sendf,"Subject: ");
  555.       fprintfold(sendf,t.subject);
  556.       fprintf(sendf,"\r\n");
  557.     }
  558.     fprintf(sendf, "X-mailer: pilot-mail-%d.%d.%d\r\n", PILOT_LINK_VERSION,PILOT_LINK_MAJOR,PILOT_LINK_MINOR);
  559.     fprintf(sendf,"\r\n"); /* Separate header */
  560.     
  561.     if (t.body) {
  562.       fprintbody(sendf,t.body);
  563.       fprintf(sendf,"\r\n");
  564.     }
  565.     if (t.signature && sig.signature) {
  566.       char * c = sig.signature;
  567.       while ((*c == '\r') || (*c == '\n'))
  568.           c++;
  569.       if(
  570.          strncmp(c,"--",2) &&
  571.          strncmp(c,"__",2)
  572.         ) {
  573.         fprintf(sendf,"\r\n-- \r\n");
  574.       }
  575.       fprintbody(sendf,sig.signature);
  576.       fprintf(sendf,"\r\n");
  577.     }
  578.  
  579.     if (pclose(sendf) == 0) {
  580.       sent++;
  581.       if (strcmp(dispose,"keep")==0) {
  582.         dupe++;
  583.       } else if (strcmp(dispose,"delete")==0) {
  584.         dlp_DeleteRecord(sd, db, 0, id);
  585.       } else {
  586.         /* Rewrite into Filed category */
  587.         dlp_WriteRecord(sd, db, attr, id, 3, buffer, size, 0);
  588.       }
  589.     }
  590.     
  591.     free_Mail(&t);
  592.   }
  593.   }
  594.   
  595.   if (strlen(pop_host)) {
  596.   
  597.   /* POP retrieval section */
  598.   
  599.   memset((char*)&pop_addr, 0, sizeof(pop_addr));
  600.   if ((pop_addr.sin_addr.s_addr = inet_addr(pop_host))==-1) {
  601.     hostent = gethostbyname(pop_host);
  602.     if (!hostent) {
  603.       fprintf(stderr, "Unable to resolve POP host '%s'", pop_host);
  604.       goto end;
  605.     }
  606.     memcpy((char*)&pop_addr.sin_addr.s_addr, hostent->h_addr,hostent->h_length);
  607.   }
  608.   pop_addr.sin_family = AF_INET;
  609.   pop_addr.sin_port = htons(110);
  610.   
  611.   if ((popfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
  612.     perror("Unable to obtain socket");
  613.     goto end;
  614.   }
  615.   
  616.   if (connect(popfd, (struct sockaddr*)&pop_addr, sizeof(pop_addr))<0) {
  617.     fprintf(stderr, "Unable to connect to POP server '%s'\n", pop_host);
  618.     close(popfd);
  619.     goto end;
  620.   }
  621.  
  622.   read(popfd, buffer, 1024);
  623.   if (buffer[0] != '+') {
  624.     fprintf(stderr, "POP server failed to announce itself\n");
  625.     goto endpop;
  626.   }  
  627.   
  628.   sprintf(buffer, "USER %s\r\n", pop_user);
  629.   write(popfd, buffer, strlen(buffer));
  630.   read(popfd, buffer, 1024);
  631.   if (buffer[0] != '+') {
  632.     fprintf(stderr, "USER command to POP server failed\n");
  633.     goto endpop;
  634.   }
  635.  
  636.   sprintf(buffer, "PASS %s\r\n", pop_pass);
  637.   write(popfd, buffer, strlen(buffer));
  638.   read(popfd, buffer, 1024);
  639.   if (buffer[0] != '+') {
  640.     fprintf(stderr, "PASS command to POP server failed\n");
  641.     close(popfd);
  642.     goto endpop;
  643.   }
  644.   
  645.   for(i=1;1;i++) {
  646.     int len;
  647.     char * msg;
  648.     int h;
  649.     struct Mail t;
  650.     
  651.     t.to = 0;
  652.     t.from = 0;
  653.     t.cc = 0;
  654.     t.bcc = 0;
  655.     t.subject = 0;
  656.     t.replyTo = 0;
  657.     t.sentTo = 0;
  658.     t.body = 0;
  659.     t.dated = 0;
  660.     
  661.     sprintf(buffer, "LIST %d\r\n", i);
  662.     write(popfd, buffer, strlen(buffer));
  663.     l = read(popfd, buffer, 1024);
  664.     if (l<0) {
  665.       perror("Unable to read from socket");
  666.       goto endpop;
  667.     }
  668.     buffer[l] = 0;
  669.     if (buffer[0] != '+')
  670.       break;
  671.     
  672.     sscanf(buffer, "%*s %*d %d", &len);
  673.     
  674.     if (len > 16000) 
  675.       continue; 
  676.  
  677.     sprintf(buffer, "RETR %d\r\n", i);
  678.     write(popfd, buffer, strlen(buffer));
  679.     l = getpopstring(popfd, buffer);
  680.     if ((l < 0) || (buffer[0] != '+')) {
  681.       /* Weird */
  682.       continue;
  683.     } else
  684.       buffer[l] = 0;
  685.     
  686.     msg = buffer;
  687.     h = 1;
  688.     for(;;) {
  689.       if (getpopstring(popfd, msg) < 0) {
  690.         fprintf(stderr, "Error reading message\n");
  691.         goto endpop;
  692.       }
  693.       
  694.       if (h == 1) { /* Header mode */
  695.         if ((msg[0] == '.') && (msg[1] == '\n') && (msg[2] == 0)) {
  696.           break; /* End of message */
  697.         }
  698.  
  699.         if (msg[0] == '\n') {
  700.           h = 0;
  701.           header(&t, 0);
  702.         } else 
  703.           header(&t, msg);
  704.         continue;
  705.       }
  706.       
  707.       if ((msg[0] == '.') && (msg[1] == '\n') && (msg[2] == 0)) {
  708.         msg[0] = 0;
  709.         break; /* End of message */
  710.       }
  711.       
  712.       if (msg[0] == '.') {
  713.         /* Must be escape */
  714.         memmove(msg, msg+1, strlen(msg));
  715.       }
  716.       
  717.       msg += strlen(msg);
  718.     }
  719.     
  720.     /* Well, we've now got the message. I bet _you_ feel happy with yourself. */
  721.     
  722.     if (h) {
  723.       /* Oops, incomplete message, still reading headers */
  724.       fprintf(stderr, "Incomplete message %d\n", i);
  725.       free_Mail(&t);
  726.       continue;
  727.     }
  728.     
  729.     if (strlen(msg) > p.truncate) {
  730.       /* We could truncate it, but we won't for now */
  731.       fprintf(stderr, "Message %d too large (%ld bytes)\n", i, (long)strlen(msg));
  732.       free_Mail(&t);
  733.       continue;
  734.     }
  735.     
  736.     t.body = strdup(buffer);
  737.     
  738.     len = pack_Mail(&t, buffer, 0xffff);
  739.     
  740.     if (dlp_WriteRecord(sd, db, 0, 0, 0, buffer, len, 0)>0) {
  741.       rec++;
  742.       if (strcmp(pop_keep,"delete")==0) { 
  743.         sprintf(buffer, "DELE %d\r\n", i);
  744.         write(popfd, buffer, strlen(buffer));
  745.         read(popfd, buffer, 1024);
  746.         if (buffer[0] != '+') {
  747.           fprintf(stderr, "Error deleting message %d\n", i);
  748.           dupe++;
  749.         }
  750.       } else
  751.         dupe++;
  752.     } else {
  753.       fprintf(stderr,"Error writing message to Pilot\n");
  754.     }
  755.     
  756.     free_Mail(&t);
  757.   }
  758.   
  759.   sprintf(buffer, "QUIT\r\n");
  760.   write(popfd, buffer, strlen(buffer));
  761.   read(popfd, buffer, 1024);
  762.   if (buffer[0] != '+') {
  763.     fprintf(stderr, "QUIT command to POP server failed\n");
  764.   }  
  765.  
  766. endpop:  
  767.   close(popfd);
  768.   
  769.   }
  770.  
  771.   if (strlen(mh_dir)) {
  772.  
  773.       fprintf(stderr, "Reading directory %s... ", mh_dir);
  774.       fflush(stderr);
  775.  
  776.   /* MH directory reading section */
  777.   
  778.   for(i=1;1;i++) {
  779.     int len;
  780.     char * msg;
  781.     int h;
  782.     struct Mail t;
  783.     int mhmsg;
  784.     
  785.     t.to = 0;
  786.     t.from = 0;
  787.     t.cc = 0;
  788.     t.bcc = 0;
  789.     t.subject = 0;
  790.     t.replyTo = 0;
  791.     t.sentTo = 0;
  792.     t.body = 0;
  793.     t.dated = 0;
  794.     
  795.     if((mhmsg=openmhmsg(mh_dir, i))<0) {
  796.     break;
  797.     }
  798.  
  799.     fprintf(stderr, "%d ", i);
  800.     fflush(stderr);
  801.  
  802.     /* Read the message */
  803.     len=0;
  804.     while((len<sizeof(buffer)) && 
  805.       ((l=read(mhmsg, (char*)(buffer+len), (sizeof(buffer)-len)))>0)) {
  806.     len+=l;
  807.     }
  808.     buffer[len]=0;
  809.  
  810.     if(l<0) {
  811.     perror("Error while reading message");
  812.     goto endmh;
  813.     }
  814.  
  815.     msg = buffer;
  816.     h = 1;
  817.     while(h==1) {
  818.       markline(msg);
  819.       
  820.       if ((msg[0] == 0) && (msg[1] == 0)) {
  821.           break; /* End of message */
  822.       }
  823.       
  824.       if (msg[0] == 0) {
  825.           h = 0;
  826.           header(&t, 0);
  827.       } else 
  828.           header(&t, msg);
  829.       msg += strlen(msg)+1;
  830.     }
  831.  
  832.     /* When we get here, we are done with the headers */
  833.     if((*msg)==0) {
  834.     /* Empty message */
  835.     h=1;
  836.     }
  837.  
  838.     /* Well, we've now got the message. I bet _you_ feel happy with yourself. */
  839.     
  840.     if (h) {
  841.       /* Oops, incomplete message, still reading headers */
  842.       fprintf(stderr, "Incomplete message %d\n", i);
  843.       free_Mail(&t);
  844.       continue;
  845.     }
  846.  
  847.     if (strlen(msg) > p.truncate) {
  848.     /* We could truncate it, but we won't for now */
  849.     fprintf(stderr, "Message %d too large (%ld bytes)\n", i, (long)strlen(msg));
  850.     free_Mail(&t);
  851.     continue;
  852.     }
  853.     
  854.     t.body = strdup(msg);
  855.     
  856.     len = pack_Mail(&t, buffer, 0xffff);
  857.     
  858.     if (dlp_WriteRecord(sd, db, 0, 0, 0, buffer, len, 0)>0) {
  859.       rec++;
  860.       if (strcmp(pop_keep,"delete")==0) { 
  861.       char filename[1000];
  862.       sprintf(filename, "%s/%d", mh_dir, i);
  863.       close(mhmsg);
  864.       if(unlink(filename)) {
  865.           fprintf(stderr, "Error deleting message %d\n", i);
  866.           dupe++;
  867.       }
  868.       continue;
  869.       } else
  870.         dupe++;
  871.     } else {
  872.       fprintf(stderr,"Error writing message to Pilot\n");
  873.     }
  874.     
  875.     free_Mail(&t);
  876.  
  877.     close(mhmsg);
  878.   }
  879.   
  880. endmh:  
  881.   fprintf(stderr, "\n");
  882.  
  883.   }
  884.  
  885. end:  
  886.   free_MailSyncPref(&p);
  887.   free_MailSignaturePref(&sig);
  888.   free_MailAppInfo(&tai);
  889.   
  890.   dlp_ResetLastSyncPC(sd);
  891.  
  892.   /* Close the database */
  893.   dlp_CloseDB(sd, db);
  894.  
  895.   sprintf(buffer, "Finished transferring mail. %d message%s sent, %d message%s received.\n",
  896.     sent, (sent == 1) ? "" : "s", rec, (rec == 1) ? "" : "s");
  897.   if (lost || dupe)
  898.     sprintf(buffer+strlen(buffer), "(And %d lost, %d duplicated. Sorry.)\n", lost, dupe);
  899.   fprintf(stderr, buffer);  
  900.   dlp_AddSyncLogEntry(sd, buffer);
  901.  
  902.   pi_close(sd);
  903.   exit(0);
  904. }
  905.  
  906.